import { filterTree, mapTree } from "./utils/tree";

function generateAccess({ router, roles, routes }) {
  const root = router.getRoutes().find((item) => item.path === "/");

  // 获取已经有的路由名
  const names = root.children.map((item) => item.name) ?? [];

  // 生成路由
  const accessibleRoutes = generateRoutes({
    roles,
    routes
  });

  // 追加路由
  accessibleRoutes.forEach((route) => {
    // 防止重复添加
    if (names.includes(route.name)) {
      return;
    }
    root.children.push(route);
  });

  // 重新注入路由
  router.removeRoute(root.name);
  router.addRoute(root);

  // 追加完路由 使用router自己生成路由路径
  const finalRoutesMap = Object.fromEntries(
    router.getRoutes().map(({ name, path }) => [name, path])
  );

  const accessibleMenus = generateMenus(accessibleRoutes, finalRoutesMap);

  return { accessibleRoutes, accessibleMenus };
}

// 根据角色权限生成路由列表
function generateRoutes({ roles, routes }) {
  // // 这里要根据实际情况修改权限判断逻辑
  // 这里是深度优先遍历路由树，找到所有有权限访问的路由
  // const filterRoutes = filterTree(routes, (route) => {
  //   // console.log(route.path);
  //   // return roles.includes(route.path);
  // });
  // TODO 这里暂时只做简单的权限判断
  // 暂时只需要权限等级路由
  const filterRoutes = routes.filter((route) => {
    // return roles.some((role) => roles.includes(role));
    return roles.includes(route.path);
  });

  return filterRoutes;
}

// 根据路由生成菜单列表
function generateMenus(routes, finalRoutesMap) {
  const menus = mapTree(routes, (route) => {
    const { meta = {}, children } = route;
    return {
      label: meta.title,
      path: finalRoutesMap[route.name],
      name: route.name,
      icon: meta.icon,
      order: meta.order,
      show: !meta.hideInMenu,
      children: children
    };
  });
  // 对菜单进行排序，避免order=0时被替换成999的问题
  const result = menus.sort((a, b) => (a?.order ?? 999) - (b?.order ?? 999));
  // 过滤掉没有子菜单的菜单
  // 这里追加 :action 的路由 去除
  // 依旧还是 这个项目没有那么复杂 我不会去单独的设置每一个路由
  // 这里没有考虑如果只有一个子路由 是否需要隐藏 或者 只展示一个父级路由 
  return filterTree(result, (item) => {
    if (item.path.includes(":action")) {
      return false;
    }
    return item.show;
  });
}

export { generateAccess };

/**
 * 判断路由是否有权限访问
 * @param route
 * @param {string[]} access
 */
function hasAuthority(route, access) {
  //   const authority = route.meta?.authority;
  //   if (!authority) {
  //     return true;
  //   }
  const canAccess = access.some((value) => authority.includes(value));

  return canAccess || (!canAccess && menuHasVisibleWithForbidden(route));
}
